package com.weisha.bledemo;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.weisha.bledemo.application.App;
import com.weisha.bledemo.retrofit.BaseCommonResponse;
import com.weisha.bledemo.retrofit.CommonOkHttp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class DeviceActivity extends Activity {

    private final static String TAG = DeviceControlActivity.class.getSimpleName();

    public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
    public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

    private TextView mConnectionState;
    private TextView mDataField;
    private EditText et_input;
    private Button btn_open;
    private String mDeviceName;
    private String mDeviceAddress;
    private BluetoothLeService mBluetoothLeService;
    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
            new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
    private boolean mConnected = false;
//    private BluetoothGattCharacteristic mNotifyCharacteristic;
    BluetoothGattCharacteristic controlCharacteristicl,notifyCharacteristic,batteryCharacteristic;

    private final String LIST_NAME = "NAME";
    private final String LIST_UUID = "UUID";

    // Code to manage Service lifecycle.
    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }
            // Automatically connects to the device upon successful start-up initialization.
            mBluetoothLeService.connect(mDeviceAddress);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }
    };

    // Handles various events fired by the Service.
    // ACTION_GATT_CONNECTED: connected to a GATT server.
    // ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
    // ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
    // ACTION_DATA_AVAILABLE: received data from the device.  This can be a result of read
    //                        or notification operations.
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
                mConnected = true;
                updateConnectionState(R.string.connected);
                invalidateOptionsMenu();
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                mConnected = false;
                updateConnectionState(R.string.disconnected);
                invalidateOptionsMenu();
                clearUI();
            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                // Show all the supported services and characteristics on the user interface.
//                displayGattServices(mBluetoothLeService.getSupportedGattServices());
                List<BluetoothGattService> bluetoothGattServices = mBluetoothLeService.getSupportedGattServices();
                for (BluetoothGattService bluetoothGattService : bluetoothGattServices) {
                    Log.e("", " server:"
                            + bluetoothGattService.getUuid().toString());
                    List<BluetoothGattCharacteristic> characteristics = bluetoothGattService
                            .getCharacteristics();
                    for (BluetoothGattCharacteristic bluetoothGattCharacteristic : characteristics) {
                        Log.e("", " charac:"
                                + bluetoothGattCharacteristic.getUuid()
                                .toString());
//                        et_input.append(" charac:"
//                                + bluetoothGattCharacteristic.getUuid()
//                                .toString());
                        if (bluetoothGattCharacteristic.getUuid().toString()
                                .equals(GattAttributes.sendCharUUID.toString())) {
                            controlCharacteristicl = bluetoothGattCharacteristic;
//                            et_input.append("------------------赋值成功--------------");
                        } else if(bluetoothGattCharacteristic.getUuid().toString()
                                .equals(GattAttributes.receiveCharUUID.toString())){
                            notifyCharacteristic = bluetoothGattCharacteristic;
                            mBluetoothLeService.setCharacteristicNotification(notifyCharacteristic, true);
//                            mBluetoothLeService.setCharacteristicNotification(mGattService.getCharacteristic(GattAttributes.receiveCharUUID),true);
                        } else if(bluetoothGattCharacteristic.getUuid().toString()
                                .equals(GattAttributes.readCharUUID.toString())){
                            batteryCharacteristic = bluetoothGattCharacteristic;
//                            et_input.append("-------读取的特征值已经找到---------");
//                            mBluetoothLeService.readCharacteristic(batteryCharacteristic);
                        }
//                        else if("af0badb1-5b99-43cd-917a-a77bc549e3cc".equals(bluetoothGattCharacteristic.getUuid().toString())){
//                            mBluetoothLeService.readCharacteristic(bluetoothGattCharacteristic);
//                        }
                    }
                }

            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
                Log.d("aaa", data);
                displayData(data);
                if(!data.equals("")){
                    if(data.equals("0")){
                        displayData("开锁失败");
                    }else if(data.equals("1")){
                        displayData("开锁成功");
                    }else if(data.equals("3")){
                        displayData("设备ID校验失败");
                    }else {
                        App.deviceId = data;
                        getDevice(App.deviceId);
                    }
                }
            }
        }
    };

    public void getDevice(String id){
        CommonOkHttp.toGetDevice(id, new Callback<BaseCommonResponse>() {
            @Override
            public void onResponse(Call<BaseCommonResponse> call, Response<BaseCommonResponse> response) {
                if(response.isSuccessful()){
                    BaseCommonResponse base = response.body();
                    if(base.getStatus().equals("01")){
                        btn_open.setBackgroundResource(R.color.green);
                        writeAction2(1);
                    }else {
                        new AlertDialog.Builder(DeviceActivity.this)
                                .setTitle("警告")
                                .setMessage("该设备故障，请重新选择车辆！")
                                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {
                                        DeviceActivity.this.finish();
                                    }
                                })
                                .show();
//                        Toast.makeText(DeviceActivity.this,"该自行车无法使用，请重新选择自行车",Toast.LENGTH_SHORT).show();
                    }
                }else{
                    Toast.makeText(DeviceActivity.this, "服务器连接失败，检查网络后重试！",Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<BaseCommonResponse> call, Throwable t) {

            }
        });
    }


    public void writeAction(View v) {

        // 写入值
        if (controlCharacteristicl != null) {
//            String aa = str2HexStr("123");
//            controlCharacteristicl.setValue(new byte[] {Byte.parseByte(aa)});
            String wholePasswprd= App.password.replace(",","");
            Byte[] pass = Utils.str2byte(wholePasswprd);
            Byte[] verifyCode = new Byte[]{Utils.verifyCode(pass)};
            Byte[] passjiaver = Utils.bytesMerger(pass, verifyCode);
            Byte[] qianzui = new Byte[]{Byte.valueOf((byte)-86), Byte.valueOf((passjiaver.length + 1)+""), 1};
            Byte[] wholeStr = Utils.bytesMerger(qianzui, passjiaver);
            byte[] newWholeStr = new byte[wholeStr.length];
            for (int i = 0; i < wholeStr.length; i++){
                newWholeStr[i] = wholeStr[i];
            }
            controlCharacteristicl.setValue(newWholeStr);
            mBluetoothLeService.writeCharacteristic(controlCharacteristicl);
        }else{
            Toast.makeText(DeviceActivity.this, "没有写查询到写入特征值，写入失败",Toast.LENGTH_SHORT).show();
        }

    }

    public void writeAction2(int flag) {

        // 写入值
        if(1==flag) {
            if (controlCharacteristicl != null) {
                String unlock = flag+"";
                Byte[] unlockByte = Utils.str2byte(unlock);
                Byte[] verifyCode = new Byte[]{Utils.verifyCode(unlockByte)};
                Byte[] unlockjiaver = Utils.bytesMerger(unlockByte, verifyCode);
                Byte[] qianzui = new Byte[]{Byte.valueOf((byte)-86), Byte.valueOf((unlockjiaver.length + 1) + ""), 3};
                Byte[] wholeStr = Utils.bytesMerger(qianzui, unlockjiaver);
                byte[] newWholeStr = new byte[wholeStr.length];
                for (int i = 0; i < wholeStr.length; i++) {
                    newWholeStr[i] = wholeStr[i];
                }
                controlCharacteristicl.setValue(newWholeStr);
                mBluetoothLeService.writeCharacteristic(controlCharacteristicl);
            } else {
                Toast.makeText(DeviceActivity.this, "没有写查询到写入特征值，写入失败", Toast.LENGTH_SHORT).show();
            }
        }else{

        }

    }

    public void readAction(View v) {

        // 读取值
        if (batteryCharacteristic != null) {
            mBluetoothLeService.readCharacteristic(batteryCharacteristic);
        }else{
            Toast.makeText(DeviceActivity.this, "没有写查询到读取特征值，读取失败",Toast.LENGTH_SHORT).show();
        }

    }

    private void clearUI() {
        mDataField.setText(R.string.no_data);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_device);

        final Intent intent = getIntent();
        mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
        mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);

        // Sets up UI references.
        ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
        mConnectionState = (TextView) findViewById(R.id.connection_state);
        mDataField = (TextView) findViewById(R.id.data_value);
        et_input = (EditText) findViewById(R.id.et_input);
        btn_open = (Button) findViewById(R.id.btn_write);
        getActionBar().setTitle(mDeviceName);
        getActionBar().setDisplayHomeAsUpEnabled(true);
        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
        if (mBluetoothLeService != null) {
            final boolean result = mBluetoothLeService.connect(mDeviceAddress);
            Log.d(TAG, "Connect request result=" + result);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mGattUpdateReceiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
        mBluetoothLeService = null;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.gatt_services, menu);
        if (mConnected) {
            menu.findItem(R.id.menu_connect).setVisible(false);
            menu.findItem(R.id.menu_disconnect).setVisible(true);
        } else {
            menu.findItem(R.id.menu_connect).setVisible(true);
            menu.findItem(R.id.menu_disconnect).setVisible(false);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
            case R.id.menu_connect:
                mBluetoothLeService.connect(mDeviceAddress);
                return true;
            case R.id.menu_disconnect:
                mBluetoothLeService.disconnect();
                return true;
            case android.R.id.home:
                onBackPressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void updateConnectionState(final int resourceId) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mConnectionState.setText(resourceId);
            }
        });
    }

    private void displayData(String data) {
        if (data != null) {
            mDataField.setText(data);
        }
    }

    // Demonstrates how to iterate through the supported GATT Services/Characteristics.
    // In this sample, we populate the data structure that is bound to the ExpandableListView
    // on the UI.
    private void displayGattServices(List<BluetoothGattService> gattServices) {
        if (gattServices == null) return;
        String uuid = null;
        String unknownServiceString = getResources().getString(R.string.unknown_service);
        String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
        ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
        ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
                = new ArrayList<ArrayList<HashMap<String, String>>>();
        mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

        // Loops through available GATT Services.
        for (BluetoothGattService gattService : gattServices) {
            HashMap<String, String> currentServiceData = new HashMap<String, String>();
            uuid = gattService.getUuid().toString();
            currentServiceData.put(
                    LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
            currentServiceData.put(LIST_UUID, uuid);
            gattServiceData.add(currentServiceData);

            ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
                    new ArrayList<HashMap<String, String>>();
            List<BluetoothGattCharacteristic> gattCharacteristics =
                    gattService.getCharacteristics();
            ArrayList<BluetoothGattCharacteristic> charas =
                    new ArrayList<BluetoothGattCharacteristic>();

            // Loops through available Characteristics.
            for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                charas.add(gattCharacteristic);
                HashMap<String, String> currentCharaData = new HashMap<String, String>();
                uuid = gattCharacteristic.getUuid().toString();
                currentCharaData.put(
                        LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
                currentCharaData.put(LIST_UUID, uuid);
                gattCharacteristicGroupData.add(currentCharaData);
            }
            mGattCharacteristics.add(charas);
            gattCharacteristicData.add(gattCharacteristicGroupData);
        }

    }

    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }
}
